package com.legal.aid.app.service.impl;

import com.legal.aid.app.domain.doc.NewsDoc;
import com.legal.aid.app.domain.vo.LawyerDetailAppVo;
import com.legal.aid.app.domain.vo.LawyerVo;
import com.legal.aid.app.domain.vo.NewsVo;
import com.legal.aid.app.mapper.AppCollectMapper;
import com.legal.aid.app.mapper.AppLawyerMapper;
import com.legal.aid.app.service.IAppLawyerService;
import com.legal.aid.common.constant.CollectType;
import com.legal.aid.common.core.domain.entity.CommonUser;
import com.legal.aid.common.core.domain.model.AppLoginUser;
import com.legal.aid.common.utils.SecurityUtils;
import com.alibaba.fastjson2.JSON;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Service
public class AppLawyerServiceImpl implements IAppLawyerService {

    @Autowired
    private AppLawyerMapper appLawyerMapper;

    @Autowired
    private AppCollectMapper appCollectMapper;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    public List<LawyerVo> selectLawyerList(LawyerVo lawyerVo) {
        List<LawyerVo> list = appLawyerMapper.selectLawyerList(lawyerVo);
        return Optional.ofNullable(list)
                .filter(l -> !l.isEmpty())
                .orElse(Collections.emptyList());
    }

    public List<LawyerVo> getLawyerListByExpertiseId(String expertiseId) {
        // 1,2,3
        LawyerVo lawyerVo = new LawyerVo();
        lawyerVo.setExpertise(expertiseId);
        List<LawyerVo> list = appLawyerMapper.selectLawyerList(lawyerVo);
        return Optional.ofNullable(list)
                .filter(l -> !l.isEmpty())
                .orElse(Collections.emptyList());
    }

    @Override
    public List<LawyerVo> selectAttentionLawyersVoList() {
        AppLoginUser appLoginUser = SecurityUtils.getAppLoginUser();
        CommonUser user = appLoginUser.getCommonUser();
        if (user == null)
            return Collections.emptyList();
        // System.out.println(appLoginUser);
        // 根据当前登录用户id查询关注列表
        // 查询目标id列表

        List<Long> targetIds = appCollectMapper.getTargetIdList(String.valueOf(CollectType.COLLECT_TYPE_LAWYER),
                user.getId());
        if (targetIds == null || targetIds.isEmpty())
            return Collections.emptyList();
        // 根据targetId 查询关注新闻
        List<LawyerVo> list = appLawyerMapper.selectLawyersListByIds(targetIds);
        return Optional.ofNullable(list)
                .filter(l -> !l.isEmpty())
                .orElse(Collections.emptyList());
    }

    @Override
    public LawyerDetailAppVo getLawyerDetailByUserId(String userId) {
        if (userId == null || userId.isEmpty())
            return null;
        return appLawyerMapper.getLawyerDetailByUserId(userId);
    }

    @Override
    public List<LawyerVo> searchLawyerByKeyword(String keyword, int pageNum, int pageSize) {
        // 1. 先查law_category，获取字典值
        List<String> codes = getCategoryCodesByKeyword(keyword);
        // 2. 用字典值查lawyer索引
        List<LawyerVo> lawyers = getLawyersByExpertiseCodes(codes, pageNum, pageSize);
        return lawyers;
    }

    /**
     * 自动补全 根据输入的prefix s
     */
    @Override
    public List<String> getLawyerSuggestions(String prefix) {
        List<String> categoryCodes = new java.util.ArrayList<>();
        try {
            SearchRequest searchRequest = new SearchRequest("law_category");
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            sourceBuilder.query(QueryBuilders.matchQuery("keywords", prefix));
            searchRequest.source(sourceBuilder);
            SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            for (SearchHit hit : response.getHits().getHits()) {
                Object code = hit.getSourceAsMap().get("category_name");
                if (code != null) {
                    categoryCodes.add(code.toString());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return categoryCodes;
    }

    @Override
    public int updateLawyerToEs() {
        LawyerVo lawyerVo = new LawyerVo();
        List<LawyerVo> list = appLawyerMapper.selectLawyerList(lawyerVo);
        // 1.创建Request
        BulkRequest bulkRequest = new BulkRequest();
        // 2.准备参数
        for (LawyerVo lawyerVo1 : list) {
            // 是 1,2,3 这种数据需要转成
            // TODO

            String[] expertiseArr = (lawyerVo1.getExpertise() != null && !lawyerVo1.getExpertise().isEmpty())
                    ? lawyerVo1.getExpertise().split(",")
                    : new String[0];

            Map<String, Object> doc = JSON.parseObject(JSON.toJSONString(lawyerVo1), Map.class);
            doc.put("expertise", expertiseArr);
            bulkRequest.add(new IndexRequest("lawyer")
                    .id(lawyerVo1.getLawyerId().toString())
                    .source(JSON.toJSONString(doc), XContentType.JSON));
        }
        // 3.发送请求
        BulkResponse bulkResponse = null;
        try {
            bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);

            System.out.println(bulkResponse.hasFailures());
            return !bulkResponse.hasFailures() ? 1 : 0;
        } catch (IOException e) {
            e.printStackTrace();
            return 1;
        }
    }

    /**
     * 查询law_category索引，获取匹配的主分类字典值
     */
    private List<String> getCategoryCodesByKeyword(String keyword) {
        List<String> categoryCodes = new java.util.ArrayList<>();
        try {
            SearchRequest searchRequest = new SearchRequest("law_category");
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            sourceBuilder.query(QueryBuilders.matchQuery("keywords", keyword));
            searchRequest.source(sourceBuilder);
            SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            for (SearchHit hit : response.getHits().getHits()) {
                Object code = hit.getSourceAsMap().get("category_code");
                if (code != null) {
                    categoryCodes.add(code.toString());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return categoryCodes;
    }

    /**
     * 查询律师索引，按expertise匹配字典值
     */
    private List<LawyerVo> getLawyersByExpertiseCodes(List<String> codes, int pageNum, int pageSize) {
        List<LawyerVo> result = new java.util.ArrayList<>();
        if (codes == null || codes.isEmpty())
            return result;
        try {
            SearchRequest searchRequest = new SearchRequest("lawyer");
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            sourceBuilder.query(QueryBuilders.termsQuery("expertise", codes));
            sourceBuilder.from((pageNum - 1) * pageSize);
            sourceBuilder.size(pageSize);
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.field("lawyer_name");
            highlightBuilder.preTags("<em>");
            highlightBuilder.postTags("</em>");
            sourceBuilder.highlighter(highlightBuilder);
            searchRequest.source(sourceBuilder);
            SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            for (SearchHit hit : response.getHits().getHits()) {
                LawyerVo lawyer = JSON.parseObject(hit.getSourceAsString(), LawyerVo.class);
                // 高亮处理
                HighlightField nameHighlight = hit.getHighlightFields().get("lawyer_name");
                if (nameHighlight != null) {
                    lawyer.setLawyerName(nameHighlight.fragments()[0].string());
                }
                result.add(lawyer);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public LawyerDetailAppVo getLawyerDetailByLawyerId(String lawyerId) {
        if (lawyerId == null || lawyerId.isEmpty())
            return null;
        return appLawyerMapper.getLawyerDetailByLawyerId(lawyerId);
    }
}
